---
title: Options
description: Discover how to customize Embla Carousel with its available options.
order: 0
date: 2021-02-21
---

import { Tabs } from 'components/Tabs/Tabs'
import { TabsItem } from 'components/Tabs/TabsItem'
import { TABS_LIBRARY } from 'consts/tabs'

# Options

Embla Carousel takes various **options** in order to customize how the carousel works.

---

## Usage

You can provide **options** in **two different ways**: With the [constructor options](/api/options/#constructor-options) and/or [global options](/api/options/#global-options). If both are provided, they will be merged, and if any options are in conflict, the **constructor option** has precedence and will **override global options**.

### Constructor options

The constructor options is the default way of providing options to Embla Carousel. In the following example, the carousel [loop](/api/options/#loop) option is set to `true`:

<Tabs groupId={TABS_LIBRARY.GROUP_ID}>
<TabsItem tab={TABS_LIBRARY.TABS.VANILLA}>

```js highlight={4}
import EmblaCarousel from 'embla-carousel'

const emblaNode = document.querySelector('.embla')
const emblaApi = EmblaCarousel(emblaNode, { loop: true })
```

</TabsItem>
<TabsItem tab={TABS_LIBRARY.TABS.REACT}>

```jsx highlight={4}
import useEmblaCarousel from 'embla-carousel-react'

export function EmblaCarousel() {
  const [emblaRef] = useEmblaCarousel({ loop: true })

  // ...
}
```

</TabsItem>
<TabsItem tab={TABS_LIBRARY.TABS.VUE}>

```html highlight={4}
<script setup>
  import emblaCarouselVue from 'embla-carousel-vue'

  const [emblaRef] = emblaCarouselVue({ loop: true })

  // ...
</script>
```

</TabsItem>
<TabsItem tab={TABS_LIBRARY.TABS.SOLID}>

```jsx highlight={4}
import createEmblaCarousel from 'embla-carousel-solid'

export function EmblaCarousel() {
  const [emblaRef] = createEmblaCarousel(() => ({ loop: true }))

  // ...
}
```

</TabsItem>
<TabsItem tab={TABS_LIBRARY.TABS.SVELTE}>

```html highlight={4,7}
<script>
  import emblaCarouselSvelte from 'embla-carousel-svelte'

  let options = { loop: true }
</script>

<div class="embla" use:emblaCarouselSvelte="{{ options }}">...</div>
```

</TabsItem>
</Tabs>

### Global options

Setting **global options** will be applied to **all carousels** which will override the Embla default options with your own. In the following example [loop](/api/options/#loop) is set to `true`:

<Tabs groupId={TABS_LIBRARY.GROUP_ID}>
<TabsItem tab={TABS_LIBRARY.TABS.VANILLA}>

```js highlight={3}
import EmblaCarousel from 'embla-carousel'

EmblaCarousel.globalOptions = { loop: true }

const emblaNode = document.querySelector('.embla')
const emblaApi = EmblaCarousel(emblaNode, { align: 'start' })
```

</TabsItem>
<TabsItem tab={TABS_LIBRARY.TABS.REACT}>

```jsx highlight={3}
import useEmblaCarousel from 'embla-carousel-react'

useEmblaCarousel.globalOptions = { loop: true }

export function EmblaCarousel() {
  const [emblaRef] = useEmblaCarousel({ align: 'start' })

  // ...
}
```

</TabsItem>
<TabsItem tab={TABS_LIBRARY.TABS.VUE}>

```html highlight={4}
<script setup>
  import emblaCarouselVue from 'embla-carousel-vue'

  emblaCarouselVue.globalOptions = { loop: true }

  const [emblaRef] = emblaCarouselVue({ align: 'start' })

  // ...
</script>
```

</TabsItem>
<TabsItem tab={TABS_LIBRARY.TABS.SOLID}>

```jsx highlight={3}
import createEmblaCarousel from 'embla-carousel-solid'

createEmblaCarousel.globalOptions = { loop: true }

export function EmblaCarousel() {
  const [emblaRef] = createEmblaCarousel(() => ({ align: 'start' }))

  // ...
}
```

</TabsItem>
<TabsItem tab={TABS_LIBRARY.TABS.SVELTE}>

```html highlight={4}
<script>
  import emblaCarouselSvelte from 'embla-carousel-svelte'

  emblaCarouselSvelte.globalOptions = { loop: true }

  let options = { align: 'start' }
</script>

<div class="embla" use:emblaCarouselSvelte="{{ options }}">...</div>
```

</TabsItem>
</Tabs>

<Admonition type="warning">
  Make sure to assign global options **before** initializing any carousel and
  **only assign it once**. Re-assigning global options might lead to confusing
  code and unexpected behaviour.
</Admonition>

### Changing options

It's possible to **change options** passed to the Embla Carousel constructor **after initialization** with the [reInit](/api/methods/#reinit) method.

In [React](/get-started/react/), [Vue](/get-started/vue/), [Solid](/get-started/solid/) and [Svelte](/get-started/svelte/) wrappers you can pass **reactive options** and the carousel will automatically reinitialize when they change. Here are some examples:

<Tabs groupId={TABS_LIBRARY.GROUP_ID}>
<TabsItem tab={TABS_LIBRARY.TABS.VANILLA}>

```js highlight={6}
import EmblaCarousel from 'embla-carousel'

const emblaNode = document.querySelector('.embla')
const emblaApi = EmblaCarousel(emblaNode, { loop: true })

emblaApi.reInit({ loop: false })
```

</TabsItem>
<TabsItem tab={TABS_LIBRARY.TABS.REACT}>

```jsx highlight={5,9-12}
import { useState, useCallback } from 'react'
import useEmblaCarousel from 'embla-carousel-react'

export function EmblaCarousel() {
  const [options, setOptions] = useState({ loop: true })
  const [emblaRef, emblaApi] = useEmblaCarousel(options)

  const toggleLoop = useCallback(() => {
    setOptions((currentOptions) => ({
      ...currentOptions,
      loop: !currentOptions.loop
    }))
  }, [])

  // ...
}
```

</TabsItem>
<TabsItem tab={TABS_LIBRARY.TABS.VUE}>

```html highlight={4,8-11}
<script setup>
  import emblaCarouselVue from 'embla-carousel-vue'

  const options = ref({ loop: true })
  const [emblaRef, emblaApi] = emblaCarouselVue(options)

  function toggleLoop() {
    options.value = {
      ...options.value,
      loop: !options.value.loop
    }
  }

  // ...
</script>
```

</TabsItem>
<TabsItem tab={TABS_LIBRARY.TABS.SOLID}>

```jsx highlight={5,9-12}
import { createSignal } from 'solid-js'
import createEmblaCarousel from 'embla-carousel-solid'

export function EmblaCarousel() {
  const [options, setOptions] = createSignal({ loop: true })
  const [emblaRef] = createEmblaCarousel(() => options())

  function toggleLoop() {
    setOptions((currentOptions) => ({
      ...currentOptions,
      loop: !currentOptions.loop
    }))
  }

  // ...
}
```

</TabsItem>
<TabsItem tab={TABS_LIBRARY.TABS.SVELTE}>

```html highlight={7-10}
<script>
  import emblaCarouselSvelte from 'embla-carousel-svelte'

  let options = { loop: true }

  function toggleLoop() {
    options = {
      ...options,
      loop: !options.loop
    }
  }
</script>

<div class="embla" use:emblaCarouselSvelte="{{ options }}">...</div>
```

</TabsItem>
</Tabs>

### TypeScript

The `EmblaOptionsType` is obtained directly from the **core package** `embla-carousel` and used like so:

<Tabs groupId={TABS_LIBRARY.GROUP_ID}>
<TabsItem tab={TABS_LIBRARY.TABS.VANILLA}>

```ts asLanguage=tsx highlight={1,4}
import EmblaCarousel, { EmblaOptionsType } from 'embla-carousel'

const emblaNode = document.querySelector('.embla')
const options: EmblaOptionsType = { loop: true }
const emblaApi = EmblaCarousel(emblaNode, options)
```

</TabsItem>
<TabsItem tab={TABS_LIBRARY.TABS.REACT}>

```tsx highlight={2,6}
import React from 'react'
import { EmblaOptionsType } from 'embla-carousel'
import useEmblaCarousel from 'embla-carousel-react'

type PropType = {
  options?: EmblaOptionsType
}

export function EmblaCarousel(props: PropType) {
  const [emblaRef, emblaApi] = useEmblaCarousel(props.options)

  // ...
}
```

<Admonition type="warning">
  If you're using `pnpm`, you need to install `embla-carousel` as a
  **devDependency** when importing types from it like demonstrated above.
  <br />
  This is because even though `embla-carousel-react` has `embla-carousel` as a
  dependency, `pnpm` makes nested dependencies inaccessible by design.
</Admonition>

</TabsItem>
<TabsItem tab={TABS_LIBRARY.TABS.VUE}>

```html highlight={2,5}
<script setup lang="ts">
  import { EmblaOptionsType } from 'embla-carousel'
  import emblaCarouselVue from 'embla-carousel-vue'

  const options: EmblaOptionsType = { loop: true }
  const [emblaRef] = emblaCarouselVue(options)

  // ...
</script>
```

<Admonition type="warning">
  If you're using `pnpm`, you need to install `embla-carousel` as a
  **devDependency** when importing types from it like demonstrated above.
  <br />
  This is because even though `embla-carousel-vue` has `embla-carousel` as a
  dependency, `pnpm` makes nested dependencies inaccessible by design.
</Admonition>

</TabsItem>
<TabsItem tab={TABS_LIBRARY.TABS.SOLID}>

```tsx highlight={1,5}
import { EmblaOptionsType } from 'embla-carousel'
import createEmblaCarousel from 'embla-carousel-solid'

type PropType = {
  options?: EmblaOptionsType
}

export function EmblaCarousel(props) {
  const [emblaRef] = createEmblaCarousel(props.options)

  // ...
}
```

<Admonition type="warning">
  If you're using `pnpm`, you need to install `embla-carousel` as a
  **devDependency** when importing types from it like demonstrated above.
  <br />
  This is because even though `embla-carousel-solid` has `embla-carousel` as a
  dependency, `pnpm` makes nested dependencies inaccessible by design.
</Admonition>

</TabsItem>
<TabsItem tab={TABS_LIBRARY.TABS.SVELTE}>

```html highlight={2,5}
<script>
  import { EmblaOptionsType } from 'embla-carousel'
  import emblaCarouselSvelte from 'embla-carousel-svelte'

  let options: EmblaOptionsType = { loop: true }
</script>

<div class="embla" use:emblaCarouselSvelte="{{ options }}">...</div>
```

<Admonition type="warning">
  If you're using `pnpm`, you need to install `embla-carousel` as a
  **devDependency** when importing types from it like demonstrated above.
  <br />
  This is because even though `embla-carousel-svelte` has `embla-carousel` as a
  dependency, `pnpm` makes nested dependencies inaccessible by design.
</Admonition>

</TabsItem>
</Tabs>

## Reference

Below follows an exhaustive **list of all** Embla Carousel **options** and their default values.

---

### active

Type: <BrandPrimaryText>`boolean`</BrandPrimaryText>  
Default: <BrandSecondaryText>`true`</BrandSecondaryText>

Setting this to `false` will not activate or deactivate the carousel. Useful when used together with the [breakpoints](/api/options/#breakpoints) option to toggle the carousel active/inactive depending on media queries.

---

### align

Type: <BrandPrimaryText>`string | (viewSize: number, snapSize: number, index: number) => number`</BrandPrimaryText>  
Default: <BrandSecondaryText>`center`</BrandSecondaryText>

Align the slides relative to the carousel viewport. Use one of the predefined alignments `start`, `center` or `end`. Alternatively, provide your own callback to fully customize the alignment.

---

### axis

Type: <BrandPrimaryText>`string`</BrandPrimaryText>  
Default: <BrandSecondaryText>`x`</BrandSecondaryText>

Choose scroll axis between `x` and `y`. Remember to stack your slides horizontally or vertically using CSS to match this option.

---

### breakpoints

Type: <BrandPrimaryText>`EmblaOptionsType`</BrandPrimaryText>  
Default: <BrandSecondaryText>`{}`</BrandSecondaryText>

An object with options that will be applied for a given breakpoint by overriding the options at the root level. Example: `'(min-width: 768px)': { loop: false }`.

<Admonition type="note">
  **Note:** If multiple queries match, they will be merged. And when breakpoint
  options clash, the last one in the list has precedence.
</Admonition>

---

### container

Type: <BrandPrimaryText>`string | HTMLElement | null`</BrandPrimaryText>  
Default: <BrandSecondaryText>`null`</BrandSecondaryText>

Enables choosing a custom container element which holds the slides. By **default**, Embla will choose the **first direct child element** of the **root element**. Provide either a valid `CSS selector string` or a `HTML element`.

---

### containScroll

Type: <BrandPrimaryText>`false` | `string`</BrandPrimaryText>  
Default: <BrandSecondaryText>`'trimSnaps'`</BrandSecondaryText>

Clear leading and trailing empty space that causes excessive scrolling. Use `trimSnaps` to only use snap points that trigger scrolling or `keepSnaps` to keep them.

<Admonition type="note">
  **Note:** When this is active, it will **override alignments** applied by the
  [align](#align) option for enough slides at the **start** and the **end** of
  the carousel, in order to **cover** the **leading** and **trailing space**.
</Admonition>

---

### direction

Type: <BrandPrimaryText>`string`</BrandPrimaryText>  
Default: <BrandSecondaryText>`ltr`</BrandSecondaryText>

Choose content direction between `ltr` and `rtl`.

<Admonition type="note">
  **Note:** When using `rtl`, the content direction also has to be set to RTL,
  either by using the [HTML dir
  attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir)
  or the [CSS
  direction](https://developer.mozilla.org/en-US/docs/Web/CSS/direction)
  property.
</Admonition>

---

### dragFree

Type: <BrandPrimaryText>`boolean`</BrandPrimaryText>  
Default: <BrandSecondaryText>`false`</BrandSecondaryText>

Enables momentum scrolling. The duration of the continued scrolling is proportional to how vigorous the drag gesture is.

---

### dragThreshold

Type: <BrandPrimaryText>`number`</BrandPrimaryText>  
Default: <BrandSecondaryText>`10`</BrandSecondaryText>

Drag threshold in pixels. This only affects **when** clicks are fired and not. In contrast to other carousel libraries, it will **not affect when dragging** of the carousel **starts**.

<Admonition type="note">
  **Note:** Browsers handle touch events differently than mouse events. Browsers
  won't fire the click event when a touch event includes an accidental slight
  swipe gesture. This is why this threshold only works for mouse events.
</Admonition>

---

### duration

Type: <BrandPrimaryText>`number`</BrandPrimaryText>  
Default: <BrandSecondaryText>`25`</BrandSecondaryText>

Set scroll duration when triggered by any of the API methods. Higher numbers enables slower scrolling. Drag interactions are not affected because duration is then determined by the drag force.

<Admonition type="note">
  **Note:** Duration is **not** in milliseconds because Embla uses an attraction
  physics simulation when scrolling instead of easings. Only values between
  `20`-`60` are recommended.
</Admonition>

---

### inViewThreshold

Type: <BrandPrimaryText>`IntersectionObserverInit.threshold`</BrandPrimaryText>  
Default: <BrandSecondaryText>`0`</BrandSecondaryText>

This is the Intersection Observer [threshold](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#creating_an_intersection_observer) option that will be applied to all slides.

---

### loop

Type: <BrandPrimaryText>`boolean`</BrandPrimaryText>  
Default: <BrandSecondaryText>`false`</BrandSecondaryText>

Enables **infinite looping**. Embla will apply `translateX` or `translateY` to the slides that need to change position in order to create the loop effect.

<Admonition type="note">
  Embla automatically falls back to `false` if slide content isn't enough to
  create the loop effect without visible glitches.
</Admonition>

---

### skipSnaps

Type: <BrandPrimaryText>`boolean`</BrandPrimaryText>  
Default: <BrandSecondaryText>`false`</BrandSecondaryText>

Allow the carousel to skip scroll snaps if it's dragged vigorously. Note that this option will be ignored if the [dragFree](/api/options/#dragfree) option is set to `true`.

---

### slides

Type: <BrandPrimaryText>`string | HTMLElement[] | NodeListOf<HTMLElement> | null`</BrandPrimaryText>  
Default: <BrandSecondaryText>`null`</BrandSecondaryText>

Enables using custom slide elements. By **default**, Embla will choose **all direct child elements** of its [container](/api/options/#container). Provide either a valid `CSS selector string` or a `nodeList/array` containing `HTML elements`.

<Admonition type="note">
  **Note:** Even though it's possible to provide custom slide elements, they
  still have to be **direct descendants** of the carousel container.
</Admonition>

<Admonition type="warning">
  **Warning:** If you place elements inside the carousel container that aren't
  slides, they either shouldn't have any size, or should be detached from the
  document flow with `position: absolute` or similar.
</Admonition>

---

### slidesToScroll

Type: <BrandPrimaryText>`string | number`</BrandPrimaryText>  
Default: <BrandSecondaryText>`1`</BrandSecondaryText>

Control the grouping of slides used for navigation interactions (next/prev buttons, dots, and dragging). By default, a single slide will be scrolled per interaction.

Set an integer value to scroll by a fixed number of slides on each interaction. For example, value `2` will treat every two slides as a single navigational unit.

Set to `auto` to dynamically create groups that match the number of slides visible in the viewport. For example, if 3 slides are currently visible, an `auto` setting would cause those 3 slides to be scrolled.

If using `auto` with slides of variable width, the group size will be calculated and adjusted dynamically based on how many slides fit into the viewport width at any given moment; not all groups will necessarily contain the same number of slides.

---

### startIndex

Type: <BrandPrimaryText>`number`</BrandPrimaryText>  
Default: <BrandSecondaryText>`0`</BrandSecondaryText>

Set the initial scroll snap to the given number. First snap index starts at `0`. Please note that this is not necessarily equal to the number of slides when used together with the [slidesToScroll](/api/options/#slidestoscroll) option.

---

### watchDrag

Type: <BrandPrimaryText>`boolean | (emblaApi: EmblaCarouselType, event: MouseEvent | TouchEvent) => boolean | void`</BrandPrimaryText>  
Default: <BrandSecondaryText>`true`</BrandSecondaryText>

Enables for scrolling the carousel with mouse and touch interactions. Set this to `false` to disable drag events or pass a custom callback to add your own drag logic.

<Admonition type="note">
  **Note:** When passing a custom callback it will run **before** the default
  Embla drag behaviour. Return `true` in your callback if you want Embla to run
  its default drag behaviour after your callback, or return `false` if you want
  to skip it.
</Admonition>

---

### watchFocus

Type: <BrandPrimaryText>`boolean | (emblaApi: EmblaCarouselType, event: FocusEvent) => boolean | void`</BrandPrimaryText>  
Default: <BrandSecondaryText>`true`</BrandSecondaryText>

Embla automatically watches the [slides](api/options/#slides) for focus events. The default callback fires the [slideFocus](/api/events/#slidefocus/) event and [scrolls](/api/methods/#scrollto/) to the focused element. Set this to `false` to disable this behaviour or pass a custom callback to add your own focus logic.

<Admonition type="note">
  **Note:** When passing a custom callback it will run **before** the default
  Embla focus behaviour. Return `true` in your callback if you want Embla to run
  its default focus behaviour after your callback, or return `false` if you want
  to skip it.
</Admonition>

---

### watchResize

Type: <BrandPrimaryText>`boolean | (emblaApi: EmblaCarouselType, entries: ResizeObserverEntry[]) => boolean | void`</BrandPrimaryText>  
Default: <BrandSecondaryText>`true`</BrandSecondaryText>

Embla automatically watches the [container](/api/methods/#containernode/) and [slides](/api/methods/#slidenodes/) for size changes and runs [reInit](/api/methods/#reinit/) when any size has changed. Set this to `false` to disable this behaviour or pass a custom callback to add your own resize logic.

<Admonition type="note">
  **Note:** When passing a custom callback it will run **before** the default
  Embla resize behaviour. Return `true` in your callback if you want Embla to
  run its default resize behaviour after your callback, or return `false` if you
  want to skip it.
</Admonition>

---

### watchSlides

Type: <BrandPrimaryText>`boolean | (emblaApi: EmblaCarouselType, mutations: MutationRecord[]) => boolean | void`</BrandPrimaryText>  
Default: <BrandSecondaryText>`true`</BrandSecondaryText>

Embla automatically watches the [container](/api/methods/#containernode/) for **added** and/or **removed** slides and runs [reInit](/api/methods/#reinit/) if needed. Set this to `false` to disable this behaviour or pass a custom callback to add your own slides changed logic.

<Admonition type="note">
  **Note:** When passing a custom callback it will run **before** the default
  Embla mutation behaviour. Return `true` in your callback if you want Embla to
  run its default mutation behaviour after your callback, or return `false` if
  you want to skip it.
</Admonition>

---
